// 树结构数据搜索
export function search(treeData, searchText) {
  if (!searchText) {
    return;
  }

  if (treeData && treeData.length > 0) {
    treeData.forEach((n, i, a) => {
      searchEach(n, searchText);
    });

    // 没有叶子节点的根节点也要清理掉
    let length = treeData.length;
    for (let i = length - 1; i >= 0; i--) {
      let e2 = treeData[i];
      if (!isHasChildren(e2) && e2.name.indexOf(searchText) <= -1) {
        treeData.splice(i, 1);
      }
    }
  }
}
// 对子节点进行搜索。
export function searchEach(node, value) {
  //获取每个根节点下面的层级
  let depth = getTreeDepth(node);
  for (let i = 0; i < depth - 1; i++) {
    // 记录【删除不匹配搜索内容的叶子节点】操作的次数。
    // 如果这个变量记录的操作次数为0，表示树形结构中，所有的
    // 叶子节点(不包含只有根节点的情况)都匹配搜索内容。那么就没有必要再
    // 在循环体里面遍历树了.
    let spliceCounter = 0;

    // 遍历树形结构
    traverseTree(node, n => {
      if (isHasChildren(n)) {
        if (n.name.indexOf(value) >= 0) {
          let spliceCounter = 0;
          return false;
        }
        let children = n.children;
        let length = children.length;
        // 找到不匹配搜索内容的叶子节点并删除。为了避免要删除的元素在数组中的索引改变，从后向前循环,
        // 找到匹配的元素就删除。
        for (let j = length - 1; j >= 0; j--) {
          let e3 = children[j];
          if (!isHasChildren(e3) && e3.name.indexOf(value) <= -1) {
            children.splice(j, 1);
            spliceCounter++;
          }
        }
      }
    });

    // 所有的叶子节点都匹配搜索内容，没必要再执行循环体了。
    if (spliceCounter == 0) {
      break;
    }
  }
}

// 质量内控-清单名称、清单特征、主材设备匹配检查项的清单主要材料可搜索
export function searchMaterial(treeData, searchText) {
  if (!searchText) {
    return;
  }

  if (treeData && treeData.length > 0) {
    treeData.forEach((n, i, a) => {
      searchEachMaterial(n, searchText);
    });

    // 没有叶子节点的根节点也要清理掉
    let length = treeData.length;
    for (let i = length - 1; i >= 0; i--) {
      let e2 = treeData[i];
      let html2 = '';
      if (e2.hasProblem) {
        html2 = e2.materialListResult
          .map(item => {
            return item.name + item.spec;
          })
          .join(',')
          .replace(/<[^>]+>/g, '');
      } else {
        html2 = e2.materialList
          .map(item => {
            return item.name + item.spec;
          })
          .join(',')
          .replace(/<[^>]+>/g, '');
      }
      if (!isHasChildren(e2) && html2.indexOf(searchText) <= -1) {
        treeData.splice(i, 1);
      }
    }
  }
}
// 对子节点进行搜索。
export function searchEachMaterial(node, value) {
  //获取每个根节点下面的层级
  let depth = getTreeDepth(node);
  for (let i = 0; i < depth - 1; i++) {
    // 记录【删除不匹配搜索内容的叶子节点】操作的次数。
    // 如果这个变量记录的操作次数为0，表示树形结构中，所有的
    // 叶子节点(不包含只有根节点的情况)都匹配搜索内容。那么就没有必要再
    // 在循环体里面遍历树了.
    let spliceCounter = 0;

    // 遍历树形结构
    traverseTree(node, n => {
      if (isHasChildren(n)) {
        let html = '';
        if (n.hasProblem) {
          html = n.materialListResult
            .map(item => {
              return item.name + item.spec;
            })
            .join(',')
            .replace(/<[^>]+>/g, '');
        } else {
          html = n.materialList
            .map(item => {
              return item.name + item.spec;
            })
            .join(',')
            .replace(/<[^>]+>/g, '');
        }
        if (html.indexOf(value) >= 0) {
          let spliceCounter = 0;
          return false;
        }
        let children = n.children;
        let length = children.length;
        // 找到不匹配搜索内容的叶子节点并删除。为了避免要删除的元素在数组中的索引改变，从后向前循环,
        // 找到匹配的元素就删除。
        for (let j = length - 1; j >= 0; j--) {
          let e3 = children[j];
          let html3 = '';
          if (e3.hasProblem) {
            html3 = e3.materialListResult
              .map(item => {
                return item.name + item.spec;
              })
              .join(',')
              .replace(/<[^>]+>/g, '');
          } else {
            html3 = e3.materialList
              .map(item => {
                return item.name + item.spec;
              })
              .join(',')
              .replace(/<[^>]+>/g, '');
          }
          if (!isHasChildren(e3) && html3.indexOf(value) <= -1) {
            children.splice(j, 1);
            spliceCounter++;
          }
        }
      }
    });

    // 所有的叶子节点都匹配搜索内容，没必要再执行循环体了。
    if (spliceCounter == 0) {
      break;
    }
  }
}

//非递归遍历树
export function traverseTree(node, callback) {
  if (!node) {
    return;
  }
  var stack = [];
  stack.push(node);
  var tmpNode;
  while (stack.length > 0) {
    tmpNode = stack.pop();
    callback(tmpNode);
    if (tmpNode.children && tmpNode.children.length > 0) {
      for (let i = tmpNode.children.length - 1; i >= 0; i--) {
        stack.push(tmpNode.children[i]);
      }
    }
  }
}

// 判断树形结构中的一个节点是否具有孩子节点
export function isHasChildren(node) {
  let flag = false;
  if (node.children && node.children.length > 0) {
    flag = true;
  }
  return flag;
}

// 通过传入根节点获得树的深度(层级)，是 calDepth 的调用者。
export function getTreeDepth(node) {
  if (undefined == node || null == node) {
    return 0;
  }
  // 返回结果
  let r = 0;
  // 树中当前层节点的集合。
  let currentLevelNodes = [node];
  // 判断当前层是否有节点
  while (currentLevelNodes.length > 0) {
    // 当前层有节点，深度可以加一。
    r++;
    // 下一层节点的集合。
    let nextLevelNodes = new Array();
    // 找到树中所有的下一层节点，并把这些节点放到 nextLevelNodes 中。
    for (let i = 0; i < currentLevelNodes.length; i++) {
      let e = currentLevelNodes[i];
      if (isHasChildren(e)) {
        nextLevelNodes = nextLevelNodes.concat(e.children);
      }
    }
    // 令当前层节点集合的引用指向下一层节点的集合。
    currentLevelNodes = nextLevelNodes;
  }
  return r;
}
